import ReactQuill, { Quill } from 'react-quill';
import { useState, useEffect, useRef, useMemo, useCallback } from 'react'
import 'react-quill/dist/quill.snow.css'
//转换化学公式
import { mhchemParser } from 'mhchemparser';
// //数学公式
import 'katex/dist/katex.min.css';
import ReactDOMServer from 'react-dom/server';
import { FunctionOutlined } from '@ant-design/icons';
import FormulaDialog from './FormulaDialog'
import { QuillFrame } from './style'
import './index.css'

type Props = {
  /** 失焦是否显示工具栏 true显示 false不显示*/
  isBlurShowToolbar?: boolean;
  /** 值*/
  value?: string;
  handleChange?: (data: string) => void
}

let toolbarOptions = [
  ['image'],
  ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
  // ['blockquote', 'code-block'],

  [{ 'header': 1 }, { 'header': 2 }],               // custom button values
  [{ 'list': 'ordered' }, { 'list': 'bullet' }],
  [{ 'script': 'sub' }, { 'script': 'super' }],      // superscript/subscript
  // [{ 'indent': '-1' }, { 'indent': '+1' }],          // outdent/indent
  // [{ 'direction': 'rtl' }],                         // text direction

  // [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
  // [{ 'header': [1, 2, 3, 4, 5, 6, false] }],

  [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
  // [{ 'font': [] }],
  [{ 'align': [] }],
  // ['formula'],
]

class CustomButtonModule {
  quill: any;
  options: any;
  showDialog = () => { };
  constructor(quill: any, options: any) {
    this.quill = quill
    this.options = options;

    const toolbar = this.quill.getModule('toolbar');
    //获取toolbar的html
    const toolbarHtml = toolbar.container;
    let span = document.createElement('span');
    //添加类名
    span.classList.add('ql-formats');
    span.style.cursor = 'pointer';
    let button = document.createElement('span');
    button.innerHTML = ReactDOMServer.renderToString(<FunctionOutlined />);
    button.onclick = this.handleClick.bind(this);
    span.appendChild(button);
    toolbarHtml.appendChild(span);
  }

  /** 点击按钮出现弹窗*/
  handleClick() {
    this.showDialog()
  }
}
Quill.register('modules/customButton', CustomButtonModule);

export default function Index(props: Props) {
  const {
    value = "",
    isBlurShowToolbar = true,
    handleChange = () => { }
  } = props;
  /** 富文本值*/
  const [richValue, setRichValue] = useState('');
  /** 公式值*/
  const [formulaVal, setFormulaVal] = useState('');
  /** 是否是编辑公式*/
  const isFormulaEdit = useRef(false);
  /** 编辑公式的索引*/
  const formulaIndex = useRef(0);

  const quillRef = useRef<any>(null);
  /** 这个才是quill实例*/
  const quillEditor = useRef<any>(null);
  /** 是否显示公式输入弹窗*/
  const [isShow, setIsShow] = useState(false)
  /** 是否聚焦*/
  const [isFocus, setIsFocus] = useState(false)

  /** 
   * @description 点击公式发生的事
  */
  const clickFormula = useCallback(function (this: any) {
    isFormulaEdit.current = true;
    setIsShow(true);
    setFormulaVal(this.getAttribute('data-value') || '')
    formulaIndex.current = quillEditor.current.getSelection().index
    const formulaContent = quillEditor.current.getContents(formulaIndex.current, 1)
    if (!formulaContent.ops[0].insert.formula) {
      formulaIndex.current = formulaIndex.current - 1
    }
  }, [])

  // 为公式元素添加点击事件处理函数
  const addClickEventToFormulas = useCallback(() => {
    const formulas = document.querySelectorAll('.ql-formula');
    formulas.forEach(formula => {
      formula.removeEventListener('click', clickFormula);
      formula.addEventListener('click', clickFormula);
    });
  }, [clickFormula])

  /** 富文本内容发生改变*/
  const onChange = useCallback((value: any, _delta: any, _source: any, editor: any) => {
    setRichValue(value)
    handleChange(value)
    addClickEventToFormulas()
  }, [handleChange, addClickEventToFormulas])

  /** 
   * @description 文本添加公式
   * @param {string} formula 公式
   * @param {number} insertIndex 插入位置
  */
  const addFormula = (formula: string, insertIndex?: number) => {
    if (quillEditor.current === null) {
      return;
    }
    quillEditor.current.focus();
    let index = insertIndex || quillEditor.current.getLength() - 1;
    let isTrue = true;
    let result = mhchemParser.toTex(formula, "tex")
    while (isTrue) {
      if (result.includes("\\ce")) {
        result = mhchemParser.toTex(result, "tex")
      } else {
        isTrue = false
      }
    }
    quillEditor.current.insertEmbed(index, 'formula', result)
    quillEditor.current.updateContents({
      ops: [
        { retain: index + 1 },
        { insert: ' ' }
      ]
    }, 'silent');
    quillEditor.current.setSelection(index + 2, 0);
  }

  /** 
   * @description 添加公式点击确定（Add formula Click OK）
   * @param {string} str 公式
  */
  const addFormulaClickOk = useCallback((str: string) => {
    setIsShow(false)
    setFormulaVal("")
    if (!isFormulaEdit.current) {
      addFormula(str)
    } else {
      quillEditor.current.deleteText(formulaIndex.current, 2)
      addFormula(str, formulaIndex.current)
    }
    isFormulaEdit.current = false
  }, [addFormula])

  useEffect(() => {
    if (quillRef.current !== null) {
      quillEditor.current = quillRef.current.getEditor()
      const module = quillEditor.current.getModule('customButton');
      module.showDialog = () => {
        setIsShow(true);
        setIsFocus(true);
      };
    }
  }, [])

  useEffect(() => {
    setRichValue(value)
  }, [value])


  return (
    <>
      <div style={{ height: '100px' }}></div>
      <QuillFrame $isShowToolbar={isBlurShowToolbar ? true : isFocus}>
        <ReactQuill
          ref={quillRef}
          theme="snow"
          value={richValue}
          onChange={onChange}
          modules={{
            toolbar: {
              container: toolbarOptions,
            },
            customButton: {
            },
          }}
          onBlur={() => {
            !isShow && setIsFocus(false)
          }}
          onFocus={() => {
            setIsFocus(true)
          }}
        />
      </QuillFrame>

      <FormulaDialog
        value={formulaVal}
        isOpen={isShow}
        handleOk={addFormulaClickOk}
        handleCancel={() => {
          setIsShow(false)
          setFormulaVal("")
          isFormulaEdit.current = false
        }}
        handleChange={(data: string) => {
          setFormulaVal(data)
        }}
      />
    </>
  )
}

